﻿
//n∗m 的矩形方阵，每个格子上面写了一个小写字母。
//小红站在矩形的左上角，她每次可以向右或者向下走，走到某个格子上就可以收集这个格子的字母。
//小红非常喜欢 "love" 这四个字母。她拿到一个 l 字母可以得 4 分，拿到一个 o 字母可以得 3 分
//，拿到一个 v 字母可以得 2 分，拿到一个 e 字母可以得 1 分。
//她想知道，在最优的选择一条路径的情况下，她最多能获取多少分？
//输入描述：
//500
//1≤n, m≤500
//接下来的
//�
//n 行 每行一个长度为
//�
//m 的、仅有小写字母构成的字符串，代表矩形方阵。
//输出描述：
//小红最大可能的得分。
//
//示例1
//输入：
//3 2
//ab
//cd
//ef
//复制
//输出：
//1
//复制
//说明：
//选择下、下、右）这条路径即可，可以收集到 acef 这四个字母各一次，获得 0 + 0 + 1 + 0 = 1 分。
//示例2
//输入：
//2 3
//lle
//ove
//复制
//输出：
//11


//思路：首先找出状态转移方程，然后发现可能i j从0开始要分情况处理边界（倒不如我们直接多开一行列为0的，然后从一开始放），最后直接返回要求的n行m列出的dp值就好。。这里可以用define或者const常量和数组连用。（采取的是布置数组的dp方法（更大可能是二维的做法））
#include <iostream>
using namespace std;

int main() {
    int n, m;
    cin >> n >> m;
    const int N = 501;
    char arr[N][N] = { 0 };
    int dp[N][N] = { 0 };
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            cin >> arr[i][j];
            int cur = 0;
            if (arr[i][j] == 'l') cur = 4;
            else  if (arr[i][j] == 'o')  cur = 3;
            else if (arr[i][j] == 'v')  cur = 2;
            else if (arr[i][j] == 'e') cur = 1;
            else cur = 0;

            dp[i][j] = max(dp[i][j - 1], dp[i - 1][j]) + cur;
        }
    }
    cout << dp[n][m] << endl;
}
// 64 位输出请用 printf("%lld")
